#include "stdafx.h"
#include "Fire.h"

#include "random.h"

#define RGBA(r,g,b,a) (((b)&0xFF) | (((g)&0xFF) << 8) | (((r)&0xFF) << 16) | (((a)&0xFF) << 24))

/**
* @brief CFire
*
* CFire::CFire
*
* @return
*/
CFire::CFire()
{
}

/**
* @brief FireInit
*
* FireInit
*
* @param int sx
* @param int sy
* @return void
*/
void CFire::Init(int sx, int sy)
{
	m_dwFireSx = sx;
	m_dwFireSy = sy;
	dwSize = sx * sy;

	SetSparks(20);

	// Init Fire arrays
	pArray1 = new BYTE[dwSize];
	memset(pArray1, 0, dwSize);

	pArray2 = new BYTE[dwSize];
	memset(pArray2, 0, dwSize);

	pCurrent = pArray1;

	m_pFireMask = new int[dwSize];
	memset(m_pFireMask, 0, dwSize * sizeof(int));

	m_pImageMask = new int[dwSize];
	memset(m_pImageMask, 0, dwSize * sizeof(int));

	// Init palette

	for (int i = 0; i < 64; i++)
	{
		m_dwPalette[i] = RGBA(0, 0, 0, 0);
		m_dwPalette[i + 64] = RGBA(i * 4, 0, 0, i * 2);
		m_dwPalette[i + 128] = RGBA(255, i * 4, 0, i * 2 + 128);
		m_dwPalette[i + 192] = RGBA(255, 255, i * 4, 255);
	}

	hFireDC.CreateCompatibleDC();

	m_pBitmapInfo = (BITMAPINFO*)new BYTE[sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)];
	m_pBitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	m_pBitmapInfo->bmiHeader.biWidth = m_dwFireSx;
	m_pBitmapInfo->bmiHeader.biHeight = -m_dwFireSy;
	m_pBitmapInfo->bmiHeader.biPlanes = 1;
	m_pBitmapInfo->bmiHeader.biBitCount = 32;
	m_pBitmapInfo->bmiHeader.biCompression = BI_RGB;
	m_pBitmapInfo->bmiHeader.biSizeImage = 0;

	hbmpFire.CreateDIBSection(hFireDC, m_pBitmapInfo, DIB_RGB_COLORS, (PVOID*) &m_pBits, NULL, 0);

	hFireDC.SelectBitmap(hbmpFire);
}

/**
* @brief FireClose
*
* FireClose
*
* @return void
*/
CFire::~CFire()
{
	delete pArray1;
	delete pArray2;

	if (m_pFireMask != NULL)
		delete m_pFireMask;
}

/**
 * @brief Draw
 *
 * CFire::Draw
 *
 * @param HDC hdc
 * @param int X
 * @param int Y
 * @return BOOL
 */
BOOL CFire::Draw( HDC hdc, int X, int Y )
{
	int i, j, dwIndex;

	// Set bright points
	int Sparks = CRandomMT::GetRand(m_nSparks);

	for (i = 0; i < Sparks;i++)
	{
		int x, y;

		do
		{
			x = CRandomMT::GetRand(m_dwFireSx - 2) + 1;
			y = CRandomMT::GetRand(m_dwFireSy - 2) + 1;
		}
		while (m_pFireMask[y * m_dwFireSx + x] == 0);

		SetPixel(x + 1, y - 1, 255);

		SetPixel(x, y - 1, 255);

		SetPixel(x - 1, y - 1, 255);

		SetPixel(x + 1, y, 255);

		SetPixel(x, y, 255);

		SetPixel(x - 1, y, 255);

		SetPixel(x + 1, y + 1, 255);

		SetPixel(x, y + 1, 255);

		SetPixel(x - 1, y + 1, 255);
	}

	// Smooth and shift
	BYTE* pNext = (pCurrent == pArray1) ? pArray2 : pArray1;

	for (j = 1;j < m_dwFireSy - 1;j++)
	{
		for (i = 1;i < m_dwFireSx - 1;i++)
		{
			dwIndex = i + j * m_dwFireSx;

			pNext[dwIndex - m_dwFireSx] = ((pCurrent[dwIndex - m_dwFireSx] + pCurrent[dwIndex - 1] +
																			pCurrent[dwIndex + 1] + pCurrent[dwIndex + m_dwFireSx]) * 32) / 131 ;

			if (m_pImageMask[dwIndex] != 0)
			{
				m_pBits[dwIndex] = m_dwPalette[pNext[dwIndex - m_dwFireSx]];
			}
			else
			{
				m_pBits[dwIndex] = RGBA(0, 0, 0, 255);
			}
		}
	}

	// Swap bits arrays
	pCurrent = pNext;

	// Copy bitmap to hdc
	SetDIBits(hFireDC, hbmpFire, 0, m_dwFireSy, m_pBits,	m_pBitmapInfo, DIB_RGB_COLORS);

	//
	BitBlt(hdc, X, Y, m_dwFireSx, m_dwFireSy, hFireDC, 0, 0, SRCCOPY);

	return TRUE;
}

/**
* @brief FireSetSparks
*
* FireSetSparks
*
* @param int Sparks
* @return void
*/
void CFire::SetSparks(int Sparks)
{
	m_nSparks = Sparks;
}

/**
* @brief FireGetMask
*
* FireGetMask
*
* @return int*
*/
int* CFire::GetFireMask()
{
	return m_pFireMask;
}

/**
* @brief SetPixel
*
* CFire::SetPixel
*
* @param int x
* @param int y
* @param BYTE bPixel
* @return void
*/
void CFire::SetPixel( int x, int y, BYTE bPixel )
{
	DWORD dwIndex = x + y * m_dwFireSx;
	pCurrent[dwIndex] = bPixel;
}

/**
 * @brief GetImageMask
 *
 * CFire::GetImageMask
 *
 * @return int*
 */
int* CFire::GetImageMask()
{
	return m_pImageMask;
}